﻿//     Copyright (c) Microsoft Corporation.  All rights reserved.

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Net;
using System.Net.Http;
using System.Net.Http.Formatting;
using System.Net.Http.Headers;
using System.Threading.Tasks;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

namespace Microsoft.Gateway.Utils
{
    public static class JsonLoader
    {
        public static JObject ReadJson(Uri location)
        {
            return ReadObjectAsync<JObject>(location).Result;
        }

        public async static Task<JObject> ReadJsonAsync(Uri location)
        {
            return await ReadObjectAsync<JObject>(location);
        }

        public static T ReadObject<T>(Uri location, IDictionary<string, string> requestHeaders = null)
        {
            return ReadObjectAsync<T>(location, requestHeaders).Result;
        }

        public async static Task<T> ReadObjectAsync<T>(Uri location, IDictionary<string, string> requestHeaders = null)
        {
            try
            {
                using (var client = new HttpClient())
                {
                    if (requestHeaders != null)
                    {
                        foreach (var header in requestHeaders)
                        {
                            client.DefaultRequestHeaders.TryAddWithoutValidation(header.Key, header.Value);
                        }
                    }
                    using (var response = await client.GetAsync(location))
                    {
                        if (response.IsSuccessStatusCode)
                        {
                            return await response.Content.ReadAsAsync<T>(new[] { GetJsonMediaTypeFormatter(location) });
                        }
                        else if (response.StatusCode == HttpStatusCode.NotFound)
                        {
                            return default(T);
                        }
                        else
                        {
                            response.EnsureSuccessStatusCode();
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                Trace.TraceWarning("Failure reading JSON object [{0}]. Details: {1}", location, ex);
                throw;
            }
            return default(T);
        }

        static MediaTypeFormatter GetJsonMediaTypeFormatter(Uri location)
        {
            var retval = new JsonMediaTypeFormatter
            {
                SerializerSettings = new JsonSerializerSettings
                {
                    Error = (sender, args) =>
                    {
                        Trace.TraceWarning("Error deserializing JSON object [{0}]. Details: {1}", location, args.ErrorContext.Error.Message);
                        args.ErrorContext.Handled = true;
                    }
                },
                UseDataContractJsonSerializer = false,
            };
            // To support reading objects from blob store (everything is */octet-stream
            retval.SupportedMediaTypes.Add(MediaTypeHeaderValue.Parse("application/octet-stream"));
            retval.SupportedMediaTypes.Add(MediaTypeHeaderValue.Parse("binary/octet-stream"));
            return retval;
        }
    }
}
